package com.woniuxy.portal.service.impl;

import com.woniuxy.common.consts.RedisConst;
import com.woniuxy.portal.mapper.BookMapper;
import com.woniuxy.portal.model.entity.Book;
import com.woniuxy.portal.model.vo.CartItemVo;
import com.woniuxy.portal.model.vo.CartVo;
import com.woniuxy.portal.service.CartService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.Duration;

@Service
public class CartServiceImpl implements CartService {

    private final RedisTemplate<String, CartVo> redisTemplate;
    private final BookMapper bookMapper;

    /**
     * 构造函数，用于注入指定泛型类型的RedisTemplate
     * 由于Spring容器中没有RedisTemplate<String, CartVo>这个泛型类型的Bean，
     * 只有默认的RedisTemplate<Object, Object>，因此需要手动配置该Bean配置类
     *
     * @param redisTemplate Redis模板对象，用于操作Redis中存储的CartVo数据，键为String类型，值为CartVo类型
     */
    @Autowired
    public CartServiceImpl(RedisTemplate<String, CartVo> redisTemplate,
                           BookMapper bookMapper) {
        this.redisTemplate = redisTemplate;
        this.bookMapper = bookMapper;
    }

    /**
     * 获取用户购物车对象
     * 1、从Redis中获取购物车对象
     * 2、如果没有获取到，就创建一个CartVo对象放入Redis
     *
     * @param userId 用户ID
     * @return CartVo 购物车对象
     */
    @Override
    public CartVo getCart(Long userId) {
        // 从Redis中获取购物车对象
        ValueOperations<String, CartVo> valueOperations = redisTemplate.opsForValue();
        CartVo cartVo = valueOperations.get(RedisConst.USER_CART_PREFIX + ":" + userId);

        // 如果Redis中没有购物车对象，则创建新的购物车对象并存入Redis
        if (cartVo == null) {
            cartVo = new CartVo();
            cartVo.setUserId(userId);

            valueOperations.set(RedisConst.USER_CART_PREFIX + ":" +
                    userId, cartVo, Duration.ofDays(7));
        }
        return cartVo;
    }

    /**
     * 向购物车中添加商品
     *
     * @param userId 用户ID
     * @param bookId 图书ID
     * @return 购物车对象
     */
    @Override
    public CartVo addCart(Long userId, Long bookId) {
        // 获取redis中的购物车对象
        CartVo cartVo = getCart(userId);

        // 查询图书
        Book book = bookMapper.selectById(bookId);
        // 封装购物车
        CartItemVo item = new CartItemVo(
                userId,
                bookId,
                book.getName(),
                book.getImgSrc(),
                book.getPrice(), 1
        );
        cartVo.addItem(item);

        // 将购物车对象存储到redis中，有效期7天
        redisTemplate.opsForValue().set(RedisConst.USER_CART_PREFIX + ":" +
                userId, cartVo, Duration.ofDays(7));
        return cartVo;
    }

    /**
     * 从用户购物车中移除指定商品
     *
     * @param userId 用户ID
     * @param bookId 图书ID
     */
    @Override
    public void removeCartItem(Long userId, Long bookId) {
        // 获取用户购物车
        CartVo cartVo = getCart(userId);
        // 移除指定商品
        cartVo.removeItem(bookId);
        // 将更新后的购物车保存到Redis，有效期7天
        redisTemplate.opsForValue().set(RedisConst.USER_CART_PREFIX + ":" +
                userId, cartVo, Duration.ofDays(7));
    }

    /**
     * 清空购物车
     * 该方法通过删除Redis中对应用户的购物车数据来实现清空购物车的功能
     *
     * @param userId 用户ID，用于标识需要清空购物车的具体用户
     */
    @Override
    public void clearCart(Long userId) {
        // 删除用户在Redis中的购物车数据
        redisTemplate.delete(RedisConst.USER_CART_PREFIX + ":" + userId);
    }

}
